/**********************************************************************************
 *
 * ngencontrol.h -- 
 *
 *********************************************************************************/

#define PIDTUNE 1	// When tuning the PID controller 
					// pc3 (uco empty) becomes pgain
					// pc4 (diesel empty) becomes igain
					// pc1 (water temp) becomes dgain
					
/**********************************************************************************
 *
 *
 * I/O Port Defines
 *
 *
 *********************************************************************************/

// port B
#define TACHIN	PB0
#define STARTOUT	PB1
#define DECOMPRESS PB2
#define	ESTOPBIT	PB3
#define LIMITLO	PB4
#define LIMITHI	PB5

#define PORTBDIR	(1 << STARTOUT) | (1 << DECOMPRESS)
#define PORTBPULLUPS (1 << TACHIN) | (1 << LIMITLO) | (1 << LIMITHI) | (1 << ESTOPBIT)

// PORTC
#define VOTEMP	PC0
#define WATERTEMP	PC1
#define OILPRES	PC2
#define UCOEMPTYBIT	PC3
#define DIESELEMPTYBIT PC4
#define GLOWPLUG	PC5

#define PORTCDIR	1 << GLOWPLUG

#ifndef PIDTUNE
#define PORTCPULLUPS	(1 <<UCOEMPTYBIT) | (1 << DIESELEMPTYBIT)
#else
#define PORTCPULLUPS	(1 <<UCOEMPTYBIT) | (1 << DIESELEMPTYBIT) | (1 << WATERTEMP)
#endif

// PORTD
#define	RXD	PD0
#define TXD	PD1
#define	RUNSTOPBIT	PD2
#define UCOVALVEBIT	PD3
#define	STEPPER1	PD4
#define	STEPPER2	PD5
#define	STEPPER3	PD6
#define	STEPPER4	PD7

#define PORTDDIR	(1 <<TXD) | (1 << UCOVALVEBIT) | (1 << STEPPER1) | (1 << STEPPER2) | (1 << STEPPER3) | (1 << STEPPER4)
#define PORTDPULLUPS	(1 << RUNSTOPBIT);


#define LED1	UCOVALVE

#define REALTIMECLOCKTICKS	249	// number of realtime clock ticks per second.
#define STEPPERCLOCKTICKS 150	// 255-N number of clock ticks per step (0-slow 160=fast)

/*******************************************************
 * MACRO shortcuts for various inputs
 ******************************************************/
#define STOP (PIND & (1 << RUNSTOPBIT))
#define RUN !(STOP)
#define ESTOP !(PINB & (1 << ESTOPBIT))
#define RUNNINGONUCO (PORTD & (1 << UCOVALVEBIT))
#define RUNNINGONDIESEL !RUNNINGONUCO
#define UCOEMPTY !(PINC & (1 << UCOEMPTYBIT))
#define DIESELEMPTY !(PINC & (1 <<DIESELEMPTYBIT))


/*******************************************************
 *
 * Generator control states.
 *   each state is called by the main state routine repeatedly based upon the
 *   "currentstate" variable. 
 *
 ******************************************************/
#define STOP1   0
#define START1   1
#define START2   2
#define START3   3
#define START4   4
#define START5   5
#define START6   6
#define RUN1   7
#define RUN2   8
#define MONITOR1   9
#define MONITOR2   10
#define UCO1   11
#define SHUTDOWN1   12
#define SHUTDOWN2   13
#define SHUTDOWN3   14
#define STOP2   15
#define ESTOP1   16
#define START7	17
#define START8	18
// state names
char *statenames[] = {
    "Stopped         ",               //stop1
    "Glow Plug Delay ",     //start1
    "Decompression   ",      //start2
    "Starting        ",               //start3
    "Oil Pres. Wait  ",   //start4
    "Warm Up         ",            //start5
	"Overcrank Delay ",	 //start6
    "",            //run1
    "RPM delay 1     ",         //run2
    "RPM delay 2     ",   //monitor1
    "Engine Monitor  ",      //monitor2
    "UCO Fuel",   //UCO1
    "Shutdown Purge  ",      //shutdown1
    "Shutdown wait   ",      //shutdown2
    "Manual Speed Set",   //shutdown3
    "Waiting for STOP",   //stop2
	"EMERGENCY STOP  ",	//estop1
	"Restart delay1  ",	// START7 (restart from run state)
	"Restart delay   "		// START8 (restart from START4 or START5 state)
};

// errors
#define CRANKRETRYERROR	1
#define SLOWCRANKERROR 2
#define UCOEMPTYERROR 3
#define DIESELEMPTYERROR 4
#define TACHLOSTERROR 5
#define SHUTDOWNTIMEOUTERROR 6
#define OVERSPEED 7
#define LOWOIL 8
#define OVERTEMP 9
#define MANUALESTOP 10
#define RESTARTATTEMPTS 11
#define UNKNOWNSTATE 12
#define OILLOSTERROR 13
char *errornames[] = {
	"                ",	// no error
	"Crank Retry Err.",
	"Slow Crank Speed",
	"UCO Fuel low    ",
	"Diesel Fuel Low ",
	"Tach Sensor Lost",
	"Shutdown Timeout",
	"overspeed       ",
	"low oil pressure",
	"over temperature",
	"manual estop    ",
	"restart  limit  ",
	"unknown state",
	"Lost Oil Sender "
};

/*******************************************************
 * engine variables
 * these are updated at the top of the state loop
 ******************************************************/
unsigned char oilpressure;	// oil pressure in pounds per square inch
unsigned char injtemp;      // injector line temperature in C
unsigned char watertemp;   	// water temperature in C
unsigned volatile int rpm;           // engine speed

/*******************************************************
 * state variables
 ******************************************************/
unsigned char inputchar;		// most recent character from USART.
unsigned char currentstate;  
unsigned char initstate;         // flag set to 1 on first time through a state
unsigned char crankretries;   // how many times we have tried and failed to start the engine
unsigned char restartattempts;	// how many times the engine has restarted after it has been running
unsigned int statestarttime;   // timestamp of when the state started
unsigned int stateruntime;      // the number of seconds a particular state has been running  
unsigned int displaytime=0;      // last time the display was updated
unsigned int errorstate;		// set to whatever error we have encountered
unsigned int timeout;			// time at which the current state times out

/*******************************************************
 * limits and settings. These will eventually be filled in from eeprom. 
 ******************************************************/
unsigned char startrpm=255;
unsigned char minoilpressure=30;   // 30 PSI minimum oil pressure
unsigned char glowplugdelay=3;   // 7 seconds delay for glow plug
unsigned char decompressdelay=3;   // crank for 3 seconds with decompression pulled
unsigned char crankretrylimit=4;   // retry starting the engine 4 times then give up.
unsigned char restartretrylimit=4;	//4 restarts before stopping with error
unsigned char cranktimelimit=30;   // each start attempt is 30 seconds.
unsigned char mincrankspeed=30;   // cranking needs to be at least 60 rpm
unsigned char oilpressuretimeout=10;   // oil pressure must come up in 10 seconds
unsigned int startspeed=1300;             // startspeed is the speed lever position in steps ~1100 rpm
unsigned int runspeed=2020;               // run speed position (in steps) to given 1800 rpm 
unsigned char warmuptimeout=10;      // warm up the engine for 60 seconds before setting to full runspeed
unsigned char overcranktimeout=60;   // wait for 60 seconds after a start failure before trying again
unsigned char mininjtemp=70;            // minimum injector line temp for UCO opeation = 70degC
unsigned char minwatertemp=70;      // minimum water temp for UCO operation = 70degC
unsigned int maxrpm=2200;               // anything over 2200 rpm calls for an estop
unsigned char maxwatertemp=110;      // 115degC = overheat
unsigned char purgetimeout=120;      // two minutes to purge the UCO from the lines
unsigned char shutdowntimeout=60;   // 60 seconds to stop the engine


/*******************************************************
 * Baud rate / USART
 ******************************************************/
// Baud Rate Settings. 16mhz clock.  See page 156-159 in ATMega8 Datasheet
#define BAUD2400 416
#define BAUD4800 207
#define BAUD9600 103
#define BAUD14400 68
#define BAUD19200 51
#define BAUD28800 34
#define BAUD38400 25
#define BAUD57000 16

/* UART Buffer Defines */
#define USART_RX_BUFFER_SIZE 2     /* 2,4,8,16,32,64,128 or 256 bytes */
#define USART_TX_BUFFER_SIZE 16     /* 2,4,8,16,32,64,128 or 256 bytes */
#define USART_RX_BUFFER_MASK ( USART_RX_BUFFER_SIZE - 1 )
#define USART_TX_BUFFER_MASK ( USART_TX_BUFFER_SIZE - 1 )
#if ( USART_RX_BUFFER_SIZE & USART_RX_BUFFER_MASK )
	#error RX buffer size is not a power of 2
#endif
#if ( USART_TX_BUFFER_SIZE & USART_TX_BUFFER_MASK )
	#error TX buffer size is not a power of 2
#endif

/* Static Variables */
static unsigned char USART_RxBuf[USART_RX_BUFFER_SIZE];
static volatile unsigned char USART_RxHead;
static volatile unsigned char USART_RxTail;
static unsigned char USART_TxBuf[USART_TX_BUFFER_SIZE];
static volatile unsigned char USART_TxHead;
static volatile unsigned char USART_TxTail;

/*******************************************************
 * stepper motor global variables
 ******************************************************/

static volatile int steppertarget;	// stepper motor target position
static volatile int steppercurrent;	// stepper motor current position
static volatile char laststep;		// what step number we are on
static unsigned char stepmap[] = { 	// full step sequence
				0b10010000,
				0b11000000,
				0b01100000,
				0b00110000
				};
static unsigned char steppertime = STEPPERCLOCKTICKS;

/*******************************************************
 *tachometer global variables
 ******************************************************/
static volatile long prevtachticks;	// along with tach ticks forms a 2 point moving average
static volatile long tachticks;		// Each Tach tick is 1/62500 sec
static unsigned int prevtach;		// previous tach reading
static volatile char tachoverflow;	//

/*******************************************************
 * // realtime clock global variables
 ******************************************************/
static volatile unsigned char realtime;	// realtime clock ticks 0-249
//static volatile long seconds;	// realtime clock seconds since start
static volatile unsigned int seconds;	// seconds since startup
static volatile unsigned char tenths;

/*******************************************************
 * pid variables
 ******************************************************/
#define TARGETRPM 1800			// normal rpm for a 4 pole 60hz alternator
static unsigned char pidtenths;	// last time the pid controller was called 
static int sumerror;			// sum of all the previous errors (integral)
static int lastrpm;				// previous rpm measurement (used in derivative)
static	int pgain;				// porportional gain
static	int igain;				// integral gain
static	int dgain;				// derivative gain


/*******************************************************
 * prototypes 
 ******************************************************/
void USART_Init( unsigned int baudrate );
unsigned char getch( void );
void putch( unsigned char data );
void putstr(char *str);
unsigned char testchar( void );
void print5(unsigned int x);
void print4(unsigned int x);
void print3(unsigned int x);
unsigned char readadc(void);
int getadc(unsigned char channel);
void setstepper(int target);
void recalibrate(void);
void ports_init(void);
void setstate(unsigned char nextstate);
void stop1(void);
void start1(void);
void start2(void);
void start3(void);
void start4(void);
unsigned char checkestop();
void start5(void);
void start6(void);
void start7(void);
void start8(void);
void run1(void);
void run2(void);
void monitor1(void);
void monitor2(void);
void shutdown1(void);
void shutdown2(void);
void shutdown3(void);
void stop2(void);
void estop1(void);
void getinput(void);
void updatedisplay(void );
void mainstate(void);
int pidcontroller(void);
